// Copyright 2011 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Defines the mimic extension sandbox module. As javascript code
 * modules can only be loaded once but imported multiple times, it is a good
 * choice for representing common mimic functionality.  It is also one of the
 * few methods available for cross browser-window communication and data
 * sharing.
 *
 * As per my understanding, all code and data for a module is private to the
 * extent that no priviledged code can have immediate access.  Only what is
 * specified in the EXPORT_SYMBOLS array is viewable by external code that has
 * imported a module.  Care needs to be taken that data is not directly
 * exposed or those who import can change it (at least their local copy).  That
 * is why I chose to expose only a small set functions that if executed will
 * not directly impact the functioning or integrity of the module's code and
 * data.
 *
 * NOTE: One possible security hole is alias overwriting.  Only one alias can
 * exist and it can only reference one path.  This means the last alias defined
 * is the one that is used.  If malicious extensions figure out a way to
 * "go last" then they could potentially overwrite the alias with their own and
 * subsitute their version of the code.  However, this should not be a problem
 * for Mimic as only a minimal amount of code exists outside the module and
 * that simply adds a new extension.
 *
 * NOTE: Another potential security hole may be if someone is able to
 * substitute IDL components for the those components used here.
 *
 * A small set of functions are exposed from this module allowing for the
 * detection, adding, removing, enabling, disabling, and detecting the
 * enable status of a specific extension represented by an alias (string).
 * The loading of the actual Chrome extension is all hidden with the module
 * and no data or functionality for it is exposed.
 *
 * All functions exported from the module must also have the @export JSDoc
 * to ensure the function name is preserved for external consumption.
 *
 * @author jasonstredwick@google.com (Jason Stredwick)
 */


goog.provide('mimic.module');

goog.require('console');
goog.require('mimic.ChromeExtension');
goog.require('mimic.TabManager');
goog.require('mimic.WindowManager');


/**
 * Symbols exported by the javascript code module to external users.
 * @type {Array.<string>}
 * @export
 */
var EXPORTED_SYMBOLS = [
  'addExtension',
  'containsExtension',
  'disableExtension',
  'enableExtension',
  'isExtensionEnabled',
  'removeExtension'
];


/**
 * An object to store module level data.
 * @type {!Object}
 * @private
 */
var Data_ = {
  // TODO (jasonstredwick): This method does not easily convey itself to
  // inter-extension communication and will have to be rethought later.
  extensions: {}
};


/**
 * Initialize the mimic module that controls the execution and management of
 * all mimic extensions.
 * @private
 */
mimic.module.init_ = function() {
  // Create the tab and window managers when their getInstance functions are
  // called for the first time.
  mimic.TabManager.getInstance();
  mimic.WindowManager.getInstance();
};


/**
 * External alias for addExtension.  Duplicate additions are not logged because
 * each time a new browser window opens the XUL document is executed, which
 * will try to add the extension again.  This is a design issue based around
 * the fact that Firefox does not support a "global" installation of an
 * extension; at least as far as I understand it.
 * @param {string} alias The extension's alias.
 * @export
 */
function addExtension(alias) {
  if (!containsExtension(alias)) {
    try {
      Data_.extensions[alias] = new mimic.ChromeExtension(alias);
    } catch (error) {
      console.error('mimic - addExtension: Failed to create extension.');
    }
  }
}


/**
 * External alias for containsExtension.
 * @param {string} alias The extension's alias.
 * @return {boolean} Whether or not the extension exists.
 * @export
 */
function containsExtension(alias) {
  return (alias in Data_.extensions ? true : false);
}


/**
 * External alias for disableExtension.
 * @param {string} alias The extension's alias.
 * @export
 */
function disableExtension(alias) {
  containsExtension(alias) && Data_.extensions[alias].disable();
}


/**
 * External alias for enableExtension.
 * @param {string} alias The extension's alias.
 * @export
 */
function enableExtension(alias) {
  containsExtension(alias) && Data_.extensions[alias].enable();
}


/**
 * External alias for enableExtension.
 * @param {string} alias The extension's alias.
 * @return {boolean} Whether or not the extension is enabled.
 * @export
 */
function isExtensionEnabled(alias) {
  if (containsExtension(alias)) {
    return Data_.extensions[alias].isEnabled();
  }
  return false;
}


/**
 * External alias for removeExtension.
 * @param {string} alias The extension's alias.
 * @export
 */
function removeExtension(alias) {
  if (containsExtension(alias)) {
    Data_.extensions[alias].destroy();
    delete Data_.extensions[alias];
  }
}


/**
 * Initialize the module once all functionality has been created.
 */
mimic.module.init_();

